local qmobs, qitems = {} , {} -- cache the data

local match, format, tonumber = strmatch,  format, tonumber --apparently its good for you

--taken from the wonderful LibQuixote-2.0 by kemayo
local objects_pattern = "^"..QUEST_OBJECTS_FOUND:gsub("(%%.)", "(.+)").."$" --QUEST_OBJECTS_FOUND = "%s: %d/%d" 
local monsters_pattern = "^"..QUEST_MONSTERS_KILLED:gsub("(%%.)", "(.+)").."$" --QUEST_MONSTERS_KILLED = "%s slain: %d/%d"

local function ColourGradient(perc) -- for colouring in
    if perc <= 0.5 then
        return 1, perc*2, 0
    else
        return 2 - perc*2, 1, 0
    end
end
local function AddQuest(table, title, name, have, need)
    if have ~= nil or need ~= nil then
        if table[name] then -- incase theres more than one quest wanting  the same thing
            if type(table[name]) == "string" then
                table[name] = {table[name]}
            end
            local t = table[name]
            t[#t+1] = format("%s:%d/%d", title, tonumber(have), tonumber(need))
        else
            table[name] = format("%s:%d/%d", title, tonumber(have), tonumber(need))
        end
    end
end

local qtitle, header, _, need, have, desc, qtype, mobname

--update qmobs/qitems when quest log updates
local f = CreateFrame("Frame")
f:RegisterEvent("QUEST_LOG_UPDATE")
f:SetScript("OnEvent", function()
    for i, v in pairs(qmobs) do qmobs[i] = nil end  --erase tables
    for i, v in pairs(qitems) do qitems[i] = nil end


    for questid = 1, GetNumQuestLogEntries() do
        qtitle, _, _, _, header = GetQuestLogTitle(questid)
        if not header and GetNumQuestLeaderBoards(questid) > 0 then
            for questob = 1, GetNumQuestLeaderBoards(questid) do
                desc, qtype = GetQuestLogLeaderBoard(questob, questid)
                if qtype == "monster" then
                    mobname, have, need = desc:match(monsters_pattern)
                    if mobname == nil or have == nil or need == nil then
                        AddQuest(qmobs,qtitle,desc:match("^%w+ (.+):(.+)/(.+)$")) -- Find Mankrik's Wife: 0/1
                        AddQuest(qmobs,qtitle,desc:match("^(.+) %w+:(.+)/(.+)$")) --Aether Rays Wrangled: 5/6
                    else AddQuest(qmobs,qtitle,mobname,have,need)
                    end

                elseif qtype == "item" or qtype == "object" then
                    AddQuest(qitems,qtitle,desc:match(objects_pattern))
                end
            end
        end
    end
end)

local function AddQuestTooltipLine(name, table, tooltip)
    local obs = table[name]
    if obs then
        if type(obs) == "table" then
            for i, v in ipairs(obs) do
                qtitle, have, need = match(v, "(.+:)(%d+)/(%d+)")
                tooltip:AddDoubleLine(qtitle, have.."/"..need, 1, 1, 1, ColourGradient(have/need))
            end
        else qtitle, have, need = match(obs, "(.+:)(%d+)/(%d+)")
            tooltip:AddDoubleLine(qtitle, have.."/"..need, 1, 1, 1, ColourGradient(have/need))
        end
    end
end



--Hooks
local name
GameTooltip:HookScript("OnTooltipSetItem", function(tooltip)
    name = tooltip:GetItem()
    if name then
        AddQuestTooltipLine(name, qitems, tooltip)
    end
end)

ItemRefTooltip:HookScript("OnTooltipSetItem", function(tooltip)
    name = tooltip:GetItem()
    if name then
        AddQuestTooltipLine(name, qitems, tooltip)
    end
end)


GameTooltip:HookScript("OnTooltipSetUnit", function(tooltip)
    name = tooltip:GetUnit()
    if not UnitIsPlayer("mouseover") and name then
        AddQuestTooltipLine(name, qmobs, tooltip)
    end
end)



